package Context;
use 5.010;
use strict; 

sub new
{
    my $class = shift;
    my $self = {
		types => {},
		free_term_variables => [],
	};
	
    bless $self, $class;
    return $self;
}

sub has_type{
	my $self=shift;
	my $typeName = shift;
	exists($self->{types}{$typeName})?1:0;
}

sub has_term{
	my $self = shift;
	my $term = shift;
	my $type = shift;
	if (exists($self->{types}{$type})){
		my $sclval = grep {$_ eq $term;} @{$self->{types}{$type}};
		return $sclval;
	}
	return 0;
}	
	
sub is_legal_type{
	my $self=shift;
	given(shift){
		when(/(?<lhs>.+?)\s*\-\>\s*(?<rhs>.+)/){
		  return $self->is_legal_type($+{lhs}) && $self->is_legal_type($+{rhs});
		}
		when(/(?<typeName>.+)/){
			my $typeName = uc($+{typeName});
			($self->has_type ($typeName))?return 1:say "$typeName is not a legal type";
			}	
		}
	return 0;
}

sub define_term {
	my $self = shift; 
	given (shift) {
		when (/(?<lhs>.+)\s*=\s*(?<rhs>.+)/){
			print "\nDefining $+{lhs} as $+{rhs}";
		}
		when (/(?<lhs>.+)\s*:\s*(?<rhs>.+)/){
			my $varType = uc($+{rhs});
			my $varTerm = lc($+{lhs});
			if ($self->is_legal_type($varType)){
				$self->has_term($varTerm, $varType)?
					say "Term already exists":
					push @{$self->{types}{$varType}} , $varTerm;
			} else {say "$varType is not a legal type";}
		}
		
	}
}
sub define_type {
	my $self = shift; 
	given( shift ){
		when (/(?<lhs>.*)=(?<rhs>.*)/){
			print "Not implemeted yet\n";
		}
		when (/^(?<NewTypeVariableName>[A-Za-z]+)$/){
			my $typeName = uc($+{NewTypeVariableName});
			if ($self->has_type ($typeName)) {
				say "Type already exists";
			}
			else {
				$self->{types}{$typeName} = [];
				say "Defined New Type $typeName";
			}
		}
	}
}
sub list {
	my $self = shift;
	my $ctr = 0;
	while ( my($key, $value) = each %{$self->{types}}){
		say $ctr++." -->".$key;
		foreach (@$value){say "\t$_";}
	}
}



1;